/**
 * @file request_handler.cpp
 * @brief HTTP请求处理器实现
 */

#include "request_handler.h"
#include "storage_manager.h"
#include "logger.hpp"
#include "id_generator.h"
#include "sysconfig.h"
#include <workflow/HttpUtil.h>
#include <fstream>
#include <sstream>
#include <random>
#include <chrono>
#include <filesystem>
#include <algorithm>
#include <cctype>
#include <unordered_map>
#include <unistd.h>
#include <limits.h>

/**
 * @brief 处理首页请求
 */
void RequestHandler::handleIndex(WFHttpTask* task) 
{
    protocol::HttpResponse* resp = task->get_resp();
    
    std::string html = getFrontendHtml();
    
    resp->set_status_code("200");
    resp->set_reason_phrase("OK");
    resp->add_header_pair("Content-Type", "text/html; charset=utf-8");
    resp->append_output_body(html);
}

/**
 * @brief 处理文件上传请求
 */
void RequestHandler::handleUpload(WFHttpTask* task) 
{
    protocol::HttpRequest* req = task->get_req();
    
    // 检查请求方法
    if (strcmp(req->get_method(), "POST") != 0) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Method not allowed"})", "405");
        return;
    }
    
    // 获取Content-Type
    protocol::HttpHeaderCursor cursor(req);
    std::string content_type;
    if (!cursor.find("Content-Type", content_type)) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Missing Content-Type header"})", "400");
        return;
    }
    
    // 检查是否为multipart/form-data
    if (content_type.find("multipart/form-data") == std::string::npos) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Invalid Content-Type"})", "400");
        return;
    }
    
    // 获取请求体
    const void* body_data;
    size_t body_size;
    req->get_parsed_body(&body_data, &body_size);
    
    if (!body_data || body_size == 0) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Empty request body"})", "400");
        return;
    }
    
    std::string body(static_cast<const char*>(body_data), body_size);
    
    // 解析multipart数据
    std::string filename, file_data;
    if (!parseMultipartFormData(content_type, body, filename, file_data)) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Failed to parse multipart data"})", "400");
        return;
    }
    
    if (filename.empty() || file_data.empty()) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "No file data found"})", "400");
        return;
    }
    
    // 检查文件大小
    if (file_data.size() > Config::getMaxFileSize()) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "File too large"})", "413");
        return;
    }
    
    // 生成临时文件
    std::string temp_path = generateTempFilePath();
    if (!writeToTempFile(file_data, temp_path)) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Failed to save temporary file"})", "500");
        return;
    }
    
    // 猜测MIME类型
    std::string mime_type = guessMimeType(filename);
    
    // 保存文件
    auto& storage = StorageManager::getInstance();
    UploadResult result = storage.saveUploadedFile(temp_path, filename, mime_type);
    
    if (result.success) 
    {
        // 构造成功响应
        std::ostringstream json;
        json << R"({"success": true, "file_id": ")" << result.file_id << R"(", )"
             << R"("hash": ")" << result.hash << R"(", )"
             << R"("filename": ")" << filename << R"(", )"
             << R"("filesize": )" << result.filesize << R"(, )"
             << R"("is_duplicate": )" << (result.is_duplicate ? "true" : "false") << R"(})";
        
        sendJsonResponse(task, json.str());
        Log::GetLogger("asynclogger")->Info("文件上传成功: %s -> %s", filename.c_str(), result.file_id.c_str());
    } 
    else 
    {
        // 构造失败响应
        std::ostringstream json;
        json << R"({"success": false, "error": ")" << result.error_msg << R"("})";
        Log::GetLogger("asynclogger")->Info("文件上传失败: %s", result.error_msg.c_str());
        
        sendJsonResponse(task, json.str(), "500");
    }
}

/**
 * @brief 处理文件下载请求
 */
void RequestHandler::handleDownload(WFHttpTask* task) 
{
    protocol::HttpRequest* req = task->get_req();
    
    // 检查请求方法
    if (strcmp(req->get_method(), "GET") != 0) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Method not allowed"})", "405");
        return;
    }
    
    // 从URL中提取文件ID
    const char* uri = req->get_request_uri();
    std::string file_id = extractFileId(std::string(uri));
    
    if (file_id.empty()) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Invalid file ID"})", "400");
        return;
    }
    
    // 验证文件ID格式
    if (!IdGenerator::validateId(file_id)) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Invalid file ID format"})", "400");
        return;
    }
    
    auto& storage = StorageManager::getInstance();
    
    // 获取文件信息
    FileInfo file_info;
    if (!storage.getFileInfo(file_id, file_info)) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "File not found"})", "404");
        return;
    }
    
    // 获取文件路径
    std::string file_path = storage.getFilePath(file_id);
    if (file_path.empty() || !std::filesystem::exists(file_path)) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "File not found on disk"})", "404");
        return;
    }
    
    // 更新下载计数
    storage.updateDownloadCount(file_id);
    
    // 发送文件
    sendFileResponse(task, file_path, file_info.mime_type, file_info.filename);
    
    Log::GetLogger("asynclogger")->Info("文件下载: %s (%s)", file_id.c_str(), file_info.filename.c_str());
}

/**
 * @brief 处理文件信息查询请求
 */
void RequestHandler::handleFileInfo(WFHttpTask* task) 
{
    protocol::HttpRequest* req = task->get_req();
    
    // 检查请求方法
    if (strcmp(req->get_method(), "GET") != 0) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Method not allowed"})", "405");
        return;
    }
    
    // 从URL中提取文件ID
    const char* uri = req->get_request_uri();
    std::string file_id = extractFileId(std::string(uri));
    
    if (file_id.empty()) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Invalid file ID"})", "400");
        return;
    }
    
    // 验证文件ID格式
    if (!IdGenerator::validateId(file_id)) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Invalid file ID format"})", "400");
        return;
    }
    
    auto& storage = StorageManager::getInstance();
    
    // 获取文件信息
    FileInfo file_info;
    if (!storage.getFileInfo(file_id, file_info)) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "File not found"})", "404");
        return;
    }
    
    // 构造响应JSON
    std::ostringstream json;
    json << R"({"success": true, )"
         << R"("file_id": ")" << file_info.id << R"(", )"
         << R"("filename": ")" << file_info.filename << R"(", )"
         << R"("filesize": )" << file_info.filesize << R"(, )"
         << R"("mime_type": ")" << file_info.mime_type << R"(", )"
         << R"("upload_time": ")" << file_info.upload_time << R"(", )"
         << R"("download_count": )" << file_info.download_count << R"(})";
    
    sendJsonResponse(task, json.str());
}

/**
 * @brief 解析multipart/form-data上传数据
 */
bool RequestHandler::parseMultipartFormData(const std::string& content_type,
                                          const std::string& body,
                                          std::string& filename,
                                          std::string& file_data) 
{
    // 提取boundary
    size_t boundary_pos = content_type.find("boundary=");
    if (boundary_pos == std::string::npos) 
    {
        return false;
    }
    
    std::string boundary = "--" + content_type.substr(boundary_pos + 9);
    
    // 查找文件部分
    size_t start = body.find(boundary);
    if (start == std::string::npos) {
        return false;
    }
    
    start = body.find("\r\n", start);
    if (start == std::string::npos) 
    {
        return false;
    }
    start += 2;
    
    // 查找下一个boundary
    size_t end = body.find(boundary, start);
    if (end == std::string::npos) 
    {
        return false;
    }
    
    std::string part = body.substr(start, end - start);
    
    // 分离头部和数据
    size_t headers_end = part.find("\r\n\r\n");
    if (headers_end == std::string::npos) 
    {
        return false;
    }
    
    std::string headers = part.substr(0, headers_end);
    file_data = part.substr(headers_end + 4);
    
    // 移除末尾的\r\n
    if (file_data.size() >= 2 && file_data.substr(file_data.size() - 2) == "\r\n") 
    {
        file_data = file_data.substr(0, file_data.size() - 2);
    }
    
    // 提取文件名
    size_t filename_pos = headers.find("filename=\"");
    if (filename_pos != std::string::npos) 
    {
        filename_pos += 10;
        size_t filename_end = headers.find("\"", filename_pos);
        if (filename_end != std::string::npos) 
        {
            filename = headers.substr(filename_pos, filename_end - filename_pos);
        }
    }
    
    return !filename.empty() && !file_data.empty();
}

/**
 * @brief 从URL路径中提取文件ID
 */
std::string RequestHandler::extractFileId(const std::string& path) 
{
    // /download/abc123 -> abc123
    // /info/abc123 -> abc123
    size_t last_slash = path.find_last_of('/');
    if (last_slash != std::string::npos && last_slash < path.length() - 1) 
    {
        return path.substr(last_slash + 1);
    }
    return "";
}

/**
 * @brief 猜测MIME类型
 */
std::string RequestHandler::guessMimeType(const std::string& filename) 
{
    size_t dot_pos = filename.find_last_of('.');
    if (dot_pos == std::string::npos) 
    {
        return "application/octet-stream";
    }
    
    std::string ext = filename.substr(dot_pos + 1);
    std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
    
    // 常见文件类型映射
    if (ext == "txt") return "text/plain";
    if (ext == "html" || ext == "htm") return "text/html";
    if (ext == "css") return "text/css";
    if (ext == "js") return "application/javascript";
    if (ext == "json") return "application/json";
    if (ext == "pdf") return "application/pdf";
    if (ext == "zip") return "application/zip";
    if (ext == "jpg" || ext == "jpeg") return "image/jpeg";
    if (ext == "png") return "image/png";
    if (ext == "gif") return "image/gif";
    if (ext == "svg") return "image/svg+xml";
    if (ext == "mp4") return "video/mp4";
    if (ext == "mp3") return "audio/mpeg";
    if (ext == "wav") return "audio/wav";
    
    return "application/octet-stream";
}

/**
 * @brief 生成临时文件路径
 */
std::string RequestHandler::generateTempFilePath() 
{
    auto now = std::chrono::steady_clock::now();
    auto timestamp = now.time_since_epoch().count();
    
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1000, 9999);
    
    std::ostringstream oss;
    oss << Config::getTempDir() << "/upload_" << timestamp << "_" << dis(gen);
    
    return oss.str();
}

/**
 * @brief 将数据写入临时文件
 */
bool RequestHandler::writeToTempFile(const std::string& file_data, const std::string& temp_path) 
{
    std::ofstream file(temp_path, std::ios::binary);
    if (!file.is_open()) 
    {
        Log::GetLogger("asynclogger")->Info("无法创建临时文件: %s", temp_path.c_str());
        return false;
    }
    
    file.write(file_data.data(), file_data.size());
    file.close();
    
    return file.good();
}

/**
 * @brief 发送JSON响应
 */
void RequestHandler::sendJsonResponse(WFHttpTask* task, const std::string& json_data, 
                                    const std::string& status_code) 
{
    protocol::HttpResponse* resp = task->get_resp();
    
    resp->set_status_code(status_code);
    resp->set_reason_phrase(status_code == "200" ? "OK" : "Error");
    resp->add_header_pair("Content-Type", "application/json; charset=utf-8");
    resp->append_output_body(json_data);
}

/**
 * @brief 发送文件响应
 */
void RequestHandler::sendFileResponse(WFHttpTask* task, const std::string& file_path,
                                    const std::string& mime_type, const std::string& filename) 
{
    protocol::HttpResponse* resp = task->get_resp();
    
    // 读取文件
    std::ifstream file(file_path, std::ios::binary);
    if (!file.is_open()) 
    {
        sendJsonResponse(task, R"({"success": false, "error": "Cannot read file"})", "500");
        return;
    }
    
    // 获取文件大小
    file.seekg(0, std::ios::end);
    size_t file_size = file.tellg();
    file.seekg(0, std::ios::beg);
    
    // 读取文件内容
    std::string file_content(file_size, '\0');
    file.read(&file_content[0], file_size);
    file.close();
    
    // 设置响应头
    resp->set_status_code("200");
    resp->set_reason_phrase("OK");
    resp->add_header_pair("Content-Type", mime_type);
    resp->add_header_pair("Content-Length", std::to_string(file_size));
    resp->add_header_pair("Content-Disposition", 
                         "attachment; filename=\"" + filename + "\"");
    
    // 设置响应体
    resp->append_output_body(file_content);
}

/**
 * @brief 获取项目根目录路径
 * @return std::string 项目根目录的绝对路径
 */
std::string RequestHandler::getProjectRoot() 
{
    static std::string project_root;
    if (project_root.empty()) 
    {
        // 获取可执行文件所在目录
        char exe_path[PATH_MAX];
        ssize_t count = readlink("/proc/self/exe", exe_path, PATH_MAX);
        if (count != -1) 
        {
            exe_path[count] = '\0';
            std::string exe_dir = std::filesystem::path(exe_path).parent_path();
            
            // 检查是否在build目录中运行
            if (exe_dir.find("/build") != std::string::npos) 
            {
                // 如果在build目录，则项目根目录是上级目录
                project_root = std::filesystem::path(exe_dir).parent_path();
            } 
            else 
            {
                // 否则假设就在项目根目录
                project_root = exe_dir;
            }
        } 
        else 
        {
            // 如果无法获取可执行文件路径，使用当前工作目录
            project_root = std::filesystem::current_path();
            
            // 检查当前目录是否包含frontend目录，如果不包含则尝试上级目录
            if (!std::filesystem::exists(project_root + "/frontend")) 
            {
                std::string parent_dir = std::filesystem::path(project_root).parent_path();
                if (std::filesystem::exists(parent_dir + "/frontend")) 
                {
                    project_root = parent_dir;
                }
            }
        }
        
        Log::GetLogger("asynclogger")->Info("项目根目录: %s", project_root.c_str());
    }
    return project_root;
}

/**
 * @brief 获取前端HTML页面内容
 */
std::string RequestHandler::getFrontendHtml() 
{
    // 构造HTML文件的完整路径
    std::string html_path = getProjectRoot() + "/frontend/templates/index.html";
    std::ifstream file(html_path);
    
    if (!file.is_open()) 
    {
        Log::GetLogger("asynclogger")->Info("无法打开HTML模板文件: %s", html_path.c_str());
        // 返回简单的错误页面
        return R"(
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="UTF-8">
                <title>云存储系统 - 错误</title>
            </head>
            <body>
                <h1>服务器错误</h1>
                <p>无法加载前端页面，请联系管理员。</p>
            </body>
            </html>
        )";
    }
    
    // 读取文件内容
    std::stringstream buffer;
    buffer << file.rdbuf();
    file.close();
    
    return buffer.str();
}

/**
 * @brief 处理静态文件请求
 */
void RequestHandler::handleStaticFile(WFHttpTask* task) 
{
    protocol::HttpRequest* req = task->get_req();
    protocol::HttpResponse* resp = task->get_resp();
    
    // 检查请求方法
    if (strcmp(req->get_method(), "GET") != 0) 
    {
        resp->set_status_code("405");
        resp->set_reason_phrase("Method Not Allowed");
        resp->append_output_body("<html><body><h1>405 Method Not Allowed</h1></body></html>");
        return;
    }
    
    // 获取请求路径
    const char* uri = req->get_request_uri();
    std::string path(uri);
    
    // 移除查询参数
    size_t pos = path.find('?');
    if (pos != std::string::npos) 
    {
        path = path.substr(0, pos);
    }
    
    // 构造文件系统路径 - 使用项目根目录
    std::string file_path = getProjectRoot() + "/frontend" + path;
    
    // 安全检查：防止路径遍历攻击
    if (path.find("..") != std::string::npos || path.find("//") != std::string::npos) 
    {
        Log::GetLogger("asynclogger")->Info("检测到可疑的路径遍历尝试: %s", path.c_str());
        resp->set_status_code("403");
        resp->set_reason_phrase("Forbidden");
        resp->append_output_body("<html><body><h1>403 Forbidden</h1></body></html>");
        return;
    }
    
    // 检查文件是否存在
    if (!std::filesystem::exists(file_path)) 
    {
        Log::GetLogger("asynclogger")->Info("静态文件不存在: %s", file_path.c_str());
        resp->set_status_code("404");
        resp->set_reason_phrase("Not Found");
        resp->append_output_body("<html><body><h1>404 Not Found</h1></body></html>");
        return;
    }
    
    // 检查是否为常规文件
    if (!std::filesystem::is_regular_file(file_path)) 
    {
        Log::GetLogger("asynclogger")->Info("请求的不是常规文件: %s", file_path.c_str());
        resp->set_status_code("403");
        resp->set_reason_phrase("Forbidden");
        resp->append_output_body("<html><body><h1>403 Forbidden</h1></body></html>");
        return;
    }
    
    // 读取文件内容
    std::ifstream file(file_path, std::ios::binary);
    if (!file.is_open()) 
    {
        Log::GetLogger("asynclogger")->Info("无法打开静态文件: %s", file_path.c_str());
        resp->set_status_code("500");
        resp->set_reason_phrase("Internal Server Error");
        resp->append_output_body("<html><body><h1>500 Internal Server Error</h1></body></html>");
        return;
    }
    
    // 获取文件大小
    file.seekg(0, std::ios::end);
    size_t file_size = file.tellg();
    file.seekg(0, std::ios::beg);
    
    // 读取文件内容
    std::string file_content(file_size, '\0');
    file.read(&file_content[0], file_size);
    file.close();
    
    // 获取MIME类型
    std::string mime_type = getStaticFileMimeType(file_path);
    
    // 设置响应头
    resp->set_status_code("200");
    resp->set_reason_phrase("OK");
    resp->add_header_pair("Content-Type", mime_type);
    resp->add_header_pair("Content-Length", std::to_string(file_size));
    resp->add_header_pair("Cache-Control", "public, max-age=3600"); // 缓存1小时
    
    // 设置响应体
    resp->append_output_body(file_content);
    
    Log::GetLogger("asynclogger")->Info("成功提供静态文件: %s (%zu bytes)", file_path.c_str(), file_size);
}

/**
 * @brief 获取静态文件的MIME类型
 */
std::string RequestHandler::getStaticFileMimeType(const std::string& file_path) 
{
    // 获取文件扩展名
    size_t dot_pos = file_path.find_last_of('.');
    if (dot_pos == std::string::npos) 
    {
        return "application/octet-stream";
    }
    
    std::string extension = file_path.substr(dot_pos + 1);
    
    // 转换为小写
    std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
    
    // 常见的静态文件MIME类型映射
    static const std::unordered_map<std::string, std::string> mime_types = 
    {
        {"html", "text/html; charset=utf-8"},
        {"htm", "text/html; charset=utf-8"},
        {"css", "text/css; charset=utf-8"},
        {"js", "application/javascript; charset=utf-8"},
        {"json", "application/json; charset=utf-8"},
        {"xml", "application/xml; charset=utf-8"},
        {"txt", "text/plain; charset=utf-8"},
        {"png", "image/png"},
        {"jpg", "image/jpeg"},
        {"jpeg", "image/jpeg"},
        {"gif", "image/gif"},
        {"svg", "image/svg+xml"},
        {"ico", "image/x-icon"},
        {"woff", "font/woff"},
        {"woff2", "font/woff2"},
        {"ttf", "font/ttf"},
        {"eot", "application/vnd.ms-fontobject"},
        {"pdf", "application/pdf"},
        {"zip", "application/zip"},
        {"mp4", "video/mp4"},
        {"mp3", "audio/mpeg"},
        {"wav", "audio/wav"}
    };
    
    auto it = mime_types.find(extension);
    if (it != mime_types.end()) 
    {
        return it->second;
    }
    
    return "application/octet-stream";
} 